package org.dding.web.console;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.dding.core.annotation.Service;
import org.dding.core.log.ILogger;
import org.dding.core.log.LoggerFactory;
import org.dding.core.manager.IServiceManager;
import org.dding.core.system.datasource.DataSource;
import org.dding.core.util.StandaloneXmlParser.DataSourceConfig;
import org.dding.core.util.StringUtils;
import org.dding.msc.exception.ServiceNotFoundException;
import org.dding.msc.exception.StartException;
import org.dding.msc.service.ServiceContainer;
import org.dding.msc.service.ServiceController;
import org.dding.msc.service.ServiceName;
import org.dding.msc.service.StartContext;
import org.dding.mvc.ActionSupport;
import org.dding.mvc.InvocationContext;
import org.dding.mvc.annotation.ActionMethod;
import org.dding.mvc.annotation.ActionMethod.ForwardMethod;
import org.dding.mvc.util.Pager;

@Service(name = "resourceAction")
public class ResourceAction extends ActionSupport<Object> {

	private ILogger logger = LoggerFactory.getLogger(getClass());
	private ServiceController<?> dataSource;
	ServiceContainer container;
	private static String[] properties = { "name", "state", "pool", "jndi" };
	private static Map<String, Comparator<WebDataSourceInfo>> mapping = new HashMap<String, Comparator<WebDataSourceInfo>>();

	static {
		for (String property : properties) {
			String method = "get" + property.substring(0, 1).toUpperCase()
					+ property.substring(1);
			mapping.put(property, new InternalComparator<WebDataSourceInfo>(
					method));
		}
	}

	@ActionMethod(
			name = "viewpool",
			successView = "main/poolview.jsp",
			httpMethod = ActionMethod.HttpMethod.GET)
	public void viewPool(InvocationContext invocationContext) {
		String id = invocationContext.getParameterValue("id");
		if (StringUtils.isEmpty(id)) {
			logger.info("pool name is null,can't be found.");
			return;
		}
		WebPoolConfig poolConfig = new WebPoolConfig();
		for (DataSourceConfig config : getDataSources().keySet()) {
			if (id.equals(config.pool_name)) {
				poolConfig.setPoolProperties(config.poolConfig
						.getPoolProperties());
				poolConfig.setName(id);
				break;
			}
		}
		invocationContext.getPageContext().setAttribute("poolConfig",
				poolConfig);
	}

	@ActionMethod(
			name = "viewdatasource",
			successView = "main/datasourceview.jsp",
			httpMethod = ActionMethod.HttpMethod.GET)
	public void viewDataSource(InvocationContext invocationContext) {
		String id = invocationContext.getParameterValue("id");
		if (StringUtils.isEmpty(id)) {
			logger.info("datasource name is null,can't be found.");
			return;
		}
		WebDataSourceInfo dataSourceInfo = new WebDataSourceInfo();
		for (DataSourceConfig config : getDataSources().keySet()) {
			if (id.equals(config.name)) {
				dataSourceInfo.setDriver(config.driver);
				dataSourceInfo.setUrl(config.url);
				dataSourceInfo.setUserName(config.username);
				dataSourceInfo.setPoolName(config.pool_name);
				dataSourceInfo.setEnable(config.enable);
				dataSourceInfo.setJndi(config.jndi);
				dataSourceInfo.setName(config.name);
				break;
			}
		}
		invocationContext.getPageContext().setAttribute("datasourceinfo",
				dataSourceInfo);

	}

	@ActionMethod(
			name = "listdatasource",
			successView = "main/datasourcelist.jsp",
			httpMethod = ActionMethod.HttpMethod.GET)
	public void listDataSource(InvocationContext invocationContext) {
		List<WebDataSourceInfo> result = fillAllResource();
		invocationContext.getPageContext().setAttribute("pager",
				handlePager(result, null));
	}

	@ActionMethod(
			name = "testConnection",
			httpMethod = ActionMethod.HttpMethod.GET,
			forwardMethod = ForwardMethod.FLUSH)
	public void testConnection(InvocationContext invocationContext) {
		String id = invocationContext.getParameterValue("id");
		Map<String, String> result = new HashMap<String, String>();
		boolean ok = false;
		for (Entry<DataSourceConfig, DataSource> entry : getDataSources()
				.entrySet()) {
			if (id.equals(entry.getKey().name)) {
				ok = entry.getValue().isConnection();
			}
		}
		if (ok) {
			result.put(STATUS, SUCCESS);
			result.put(MESSAGE, "连接成功!");
		} else {
			result.put(STATUS, FAILURE);
			result.put(MESSAGE, "连接失败!");
		}
		ajaxJsonMessage(result, invocationContext);
	}

	private List<WebDataSourceInfo> fillAllResource() {

		List<WebDataSourceInfo> result = new ArrayList<WebDataSourceInfo>();
		for (DataSourceConfig config : getDataSources().keySet()) {
			WebDataSourceInfo dataSourceInfo = new WebDataSourceInfo();
			dataSourceInfo.setName(config.name);
			dataSourceInfo.setEnable(config.enable);
			dataSourceInfo.setJndi(config.jndi);
			dataSourceInfo.setPoolName(config.pool_name);
			result.add(dataSourceInfo);
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	private Map<DataSourceConfig, DataSource> getDataSources() {
		dataSource = container.getService(ServiceName
				.of(IServiceManager._SYSTEM_SERVICE + "datasource"));
		return (Map<DataSourceConfig, DataSource>) dataSource.getValue();
	}

	@Override
	public void start(StartContext context) throws ServiceNotFoundException, StartException {
		super.start(context);
		container = context.getController().getServiceContainer();
	}

	@ActionMethod(
			name = "search",
			successView = "main/datasourcelist.jsp",
			invocationClass = Pager.class)
	public void search(InvocationContext invocationContext) {
		Pager pagerInvocaion = (Pager) invocationContext.getInvocation();

		String keyword = pagerInvocaion.getKeyword();
		String searchBy = pagerInvocaion.getSearchBy();

		if (StringUtils.isNotEmpty(keyword) && StringUtils.isNotEmpty(searchBy)) {
			query(invocationContext);
		} else {
			if (pagerInvocaion != null) {
				List<WebDataSourceInfo> list = fillAllResource();
				Pager pager = handlePager(list, pagerInvocaion);
				String orderBy = pager.getOrderBy();
				if (StringUtils.isNotEmpty(orderBy)) {
					Comparator<WebDataSourceInfo> comparator = mapping
							.get(orderBy);
					if (comparator != null)
						Collections.sort(list, comparator);
				}
				invocationContext.getPageContext().setAttribute("pager", pager);
			}
		}
	}

	private void query(InvocationContext invocationContext) {
		Pager pagerInvocaion = (Pager) invocationContext.getInvocation();
		String keyword = pagerInvocaion.getKeyword();
		String searchBy = pagerInvocaion.getSearchBy();
		List<WebDataSourceInfo> list = new ArrayList<WebDataSourceInfo>();
		if ("datasourceName".equalsIgnoreCase(searchBy)) {

			List<WebDataSourceInfo> datasources = fillAllResource();
			for (WebDataSourceInfo datasource : datasources) {
				if (StringUtils.containsIgnoreCase(datasource.getName(),
						keyword)) {
					list.add(datasource);
				}
			}
			invocationContext.getPageContext().setAttribute("pager",
					handlePager(list, null));
		} else {
			throw new IllegalArgumentException(
					"only support search by resource name.");
		}
	}
}
